﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;

using Hxsoft.Web.UI.WebControls;

namespace Hxsoft.AppV1
{
	// 选择框类型
	public enum SelectBoxType : byte
	{
		/// <summary>
		/// 复选框
		/// </summary>
		CheckBox,

		/// <summary>
		/// 单选框
		/// </summary>
		RadioButton
	}





	/// <summary>
	/// 选择器基类。
	/// </summary>
	/// <typeparam name="ItemType">选择项类型。</typeparam>
	public abstract class BaseSelector<ItemType> : System.Web.UI.UserControl
	{
		#region 属性
		private static readonly object EventSelectFinish = new object();
		private static readonly object EventSelectedChanged = new object();

		/// <summary>
		/// 选择类型。
		/// </summary>
		public virtual SelectBoxType SelectType
		{
			get
			{
				object oSelectType = ViewState["SelectType"];
				return oSelectType == null ? SelectBoxType.CheckBox : (SelectBoxType)oSelectType;
			}
			set { ViewState["SelectType"] = value; }
		}

		/// <summary>
		/// 选择项集合。
		/// </summary>
		public abstract List<ItemType> SelectedItems { get; }

		/// <summary>
		/// 最后选择的项。
		/// </summary>
		public ItemType SelectedItem
		{
			get
			{
				List<ItemType> selectedItems = SelectedItems;
				if (selectedItems != null && selectedItems.Count > 0)
					return selectedItems[selectedItems.Count - 1];
				return default(ItemType);
			}
		}

		/// <summary>
		/// 是否选定了值。
		/// </summary>
		public bool IsSelected
		{
			get
			{
				return (SelectedItems != null && SelectedItems.Count > 0);
			}
		}
		#endregion



		#region ItemType Method
		/// <summary>
		/// 确定两个数据项是否相同。
		/// </summary>
		/// <param name="item1">数据项1。</param>
		/// <param name="item2">数据项2。</param>
		/// <returns>布尔值表示两个数据项是否相等。</returns>
		public virtual bool ItemEquals(ItemType item1, ItemType item2)
		{
			return item1.Equals(item2);
		}

		/// <summary>
		/// 确定数据集合中是否包含数据项。
		/// </summary>
		/// <param name="items">数据集合。</param>
		/// <param name="item">数据项。</param>
		/// <returns>布尔值表示数据集合中是否包含数据项。</returns>
		public virtual bool ItemsContains(List<ItemType> items, ItemType item)
		{
			return items.Contains(item);
		}

		/// <summary>
		/// 查找数据集合中的指定项。
		/// </summary>
		/// <param name="items">数据集合。</param>
		/// <param name="item">指定的项。</param>
		/// <returns>数据集合中的指定项。</returns>
		public virtual object ItemsFind(List<ItemType> items, ItemType item)
		{
			if (ItemsContains(items, item))
				return items.Find(p => p.Equals(item));
			return null;
		}

		/// <summary>
		/// 对数据项进行数据修正。
		/// </summary>
		/// <param name="item">进行修正的数据项。</param>
		/// <param name="item2">参考的数据项。</param>
		/// <returns>布尔值表示数据是否更改。</returns>
		public virtual bool ItemChange(ref ItemType item, ItemType item2)
		{
			if (item.Equals(item2)) return false;
			return true;
		}

		/// <summary>
		/// 确保数据列表中的数据项存在，并且数据一致。
		/// </summary>
		/// <param name="items">数据项列表。</param>
		/// <param name="item">进行验证的数据项。</param>
		/// <returns>布尔值表示数据列表是否进行更改。</returns>
		public virtual bool ItemsEnsureItem(List<ItemType> items, ItemType item)
		{
			bool change = false;

			object sItem = ItemsFind(items, item);
			if (sItem == null)
			{
				items.Add(item);
				change = true;
			}
			else
			{
				ItemType rsItem = (ItemType)sItem;
				change = ItemChange(ref rsItem, item);
			}
			return change;
		}

		/// <summary>
		/// 从数据列表中移除数据项。
		/// </summary>
		/// <param name="items">数据列表。</param>
		/// <param name="item">移除的数据项。</param>
		/// <returns>数据列表是否更改。</returns>
		public virtual bool ItemsRemoveItem(List<ItemType> items, ItemType item)
		{
			return items.RemoveAll(p => p.Equals(item)) > 0;
		}
		#endregion




		#region OnSelectFinish Method
		/// <summary>
		/// 当选择结束时事件声明
		/// </summary>
		public event EventHandler SelectFinish
		{
			add
			{
				base.Events.AddHandler(EventSelectFinish, value);
			}
			remove
			{
				base.Events.RemoveHandler(EventSelectFinish, value);
			}
		}

		/// <summary>
		/// 选择结束的事件句柄
		/// </summary>
		protected virtual EventHandler SelectFinishEventHandler
		{
			get
			{
				EventHandler handler = (EventHandler)base.Events[EventSelectFinish];
				return handler;
			}
		}

		/// <summary>
		/// 引发 <see cref="SelectFinish"/> 事件。这使您可以为事件提供自定义处理程序。
		/// </summary>
		/// <param name="e">一个 <see cref="EventArgs"/>，它包含事件数据。</param>
		protected virtual void OnSelectFinish(EventArgs e)
		{
			EventHandler handler = SelectFinishEventHandler;
			if (handler != null)
				handler(this, e);
		}
		#endregion

		#region OnSelectedChanged Method
		/// <summary>
		/// 当选择改变时事件声明
		/// </summary>
		public event EventHandler SelectedChanged
		{
			add
			{
				base.Events.AddHandler(EventSelectedChanged, value);
			}
			remove
			{
				base.Events.RemoveHandler(EventSelectedChanged, value);
			}
		}

		/// <summary>
		/// 当选择改变时的事件句柄
		/// </summary>
		protected virtual EventHandler SelectedChangedEventHandler
		{
			get
			{
				EventHandler handler = (EventHandler)base.Events[EventSelectedChanged];
				return handler;
			}
		}

		/// <summary>
		/// 引发 <see cref="SelectedChanged"/> 事件。这使您可以为事件提供自定义处理程序。
		/// </summary>
		/// <param name="e">一个 <see cref="EventArgs"/>，它包含事件数据。</param>
		protected virtual void OnSelectedChanged(EventArgs e)
		{
			EventHandler handler = SelectedChangedEventHandler;
			if (handler != null)
				handler(this, e);
		}
		#endregion
	}




	public abstract class ListSelector<ItemType, DataBindCollection> : BaseSelector<ItemType> where DataBindCollection : ICollection, IEnumerable, new()
	{
		#region 属性
		protected abstract Wuqi.Webdiyer.AspNetPager Pager { get; }

		protected virtual string SelectBoxContainerId { get { return "LbSelectBox"; } }
		protected virtual string SelectBoxGroupName { get { return "SelectBoxList"; } }
		protected virtual string SelectBoxId { get { return "SelectBox"; } }

		/// <summary>
		/// 选择项集合。
		/// </summary>
		public override List<ItemType> SelectedItems
		{
			get
			{
				if (ViewState["SelectedItems"] == null)
					ViewState["SelectedItems"] = new List<ItemType>();
				return (List<ItemType>)ViewState["SelectedItems"];
			}
		}
		#endregion




		#region 事件
		protected virtual void Page_Load(object sender, EventArgs e)
		{
			if (!IsPostBack)
			{
				LoadList();
				this.DataBind();
			}
			EnsureSaveSelectItems();
		}

		/// <summary>
		/// 当搜索按钮点击时触发。
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected virtual void BtSearch_Click(object sender, EventArgs e)
		{
			EnsureSaveSelectItems();

			Pager.CurrentPageIndex = 1;
			LoadList();
		}

		/// <summary>
		/// 当点击刷新按钮时触发。
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected virtual void BtReload_Click(object sender, EventArgs e)
		{
			LoadList();
		}

		/// <summary>
		/// 当点击选择按钮时触发。
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected virtual void BtSelect_Click(object sender, EventArgs e)
		{
			EnsureSaveSelectItems();
			OnSelectFinish(new EventArgs());
		}

		/// <summary>
		/// 当点击分页时触发。
		/// </summary>
		/// <param name="src"></param>
		/// <param name="e"></param>
		protected virtual void Pager_PageChanging(object src, Wuqi.Webdiyer.PageChangingEventArgs e)
		{
			EnsureSaveSelectItems();

			Pager.CurrentPageIndex = e.NewPageIndex;
			LoadList();
		}
		#endregion




		#region 函数
		/// <summary>
		/// 从数据源获取分页数据。
		/// </summary>
		/// <returns>分页数据。</returns>
		protected abstract PaginationInfo<DataBindCollection> GetData();

		/// <summary>
		/// 加载列表。
		/// </summary>
		protected abstract void LoadList();

		/// <summary>
		/// 保存选择项。
		/// </summary>
		/// <returns>返回一个布尔值表示值是否已更改。</returns>
		protected abstract bool SaveSelectItems();



		private bool isSaveSelectItems = false;
		protected void EnsureSaveSelectItems()
		{
			if (isSaveSelectItems == true) return;
			if (SaveSelectItems())
				this.OnSelectedChanged(new EventArgs());
			isSaveSelectItems = true;
		}


		public void Reload()
		{
			SelectedItems.Clear();
			LoadList();
		}
		#endregion
	}

	public abstract class RepeaterSelector<ItemType, DataBindCollection> : ListSelector<ItemType, DataBindCollection> where DataBindCollection : ICollection, IEnumerable, new()
	{
		#region 属性
		protected abstract Repeater DataList { get; }
		#endregion

		#region 事件
		/// <summary>
		/// （列表控件）创建选择器。
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected virtual void DataList_ItemCreated(object sender, RepeaterItemEventArgs e)
		{
			if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
			{
				Label SelectBoxContainer = (Label)e.Item.FindControl(SelectBoxContainerId);

				CheckBox selectBox;
				if (SelectType == SelectBoxType.CheckBox)
					selectBox = new CheckBox();
				else
				{
					selectBox = new GroupRadioButton();
					((GroupRadioButton)selectBox).GroupName = SelectBoxGroupName;
					if (this.SelectedChangedEventHandler != null) selectBox.AutoPostBack = true;
				}
				selectBox.ID = SelectBoxId;

				SelectBoxContainer.Controls.Add(selectBox);
			}
		}

		/// <summary>
		/// （列表控件）恢复选择项。
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected virtual void DataList_ItemDataBound(object sender, RepeaterItemEventArgs e)
		{
			if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
			{
				ItemType itemType = GetListItemType(e.Item);

				if (ItemsContains(SelectedItems, itemType))
				{
					CheckBox selectBox = (CheckBox)e.Item.FindControl(SelectBoxId);
					selectBox.Checked = true;
				}
			}
		}
		#endregion




		#region 函数
		/// <summary>
		/// 加载列表。
		/// </summary>
		protected override void LoadList()
		{
			PaginationInfo<DataBindCollection> pageInfo = GetData();

			Pager.RecordCount = pageInfo.RecordCount;

			DataList.DataSource = pageInfo.Records;
			DataList.DataBind();

			Pager.CustomInfoHTML = "<span class=\"PagerCustomInfo\">第 <span class=\"CurrentPage\">" + pageInfo.CurrentPage + "</span>/<span class=\"PageCount\">" + pageInfo.PageCount + "</span> 页";
			Pager.CustomInfoHTML += " 当前显示第 <span class=\"CurrentPageLimit\">" + pageInfo.CurrentPageLimit.Lower + "-" + pageInfo.CurrentPageLimit.Upper + "</span> 条记录</span>";
		}

		/// <summary>
		/// 保存选择项。
		/// </summary>
		protected override bool SaveSelectItems()
		{
			bool change = false;
			foreach (RepeaterItem item in DataList.Items)
			{
				if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
				{
					CheckBox selectBox = (CheckBox)item.FindControl(SelectBoxId);
					ItemType itemType = GetListItemType(item);
					if (selectBox.Checked)
					{
						change = change | ItemsEnsureItem(SelectedItems, itemType);
					}
					else
					{
						change = change | ItemsRemoveItem(SelectedItems, itemType);
					}
				}
			}

			if (SelectType == SelectBoxType.RadioButton && SelectedItems.Count > 1)
			{
				SelectedItems.RemoveRange(0, SelectedItems.Count - 1);
			}

			return change;
		}

		/// <summary>
		/// 取得 ListItem 的 ItemType。
		/// </summary>
		/// <param name="item">列表的 ListItem。</param>
		/// <returns>ListItem 的 ItemType。</returns>
		protected abstract ItemType GetListItemType(RepeaterItem item);
		#endregion
	}

	public abstract class DataListSelector<ItemType, DataBindCollection> : ListSelector<ItemType, DataBindCollection> where DataBindCollection : ICollection, IEnumerable, new()
	{
		#region 属性
		protected abstract DataList DataList { get; }
		#endregion

		#region 事件
		/// <summary>
		/// （列表控件）创建选择器。
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected virtual void DataList_ItemCreated(object sender, DataListItemEventArgs e)
		{
			if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
			{
				Label SelectBoxContainer = (Label)e.Item.FindControl(SelectBoxContainerId);

				CheckBox selectBox;
				if (SelectType == SelectBoxType.CheckBox)
					selectBox = new CheckBox();
				else
				{
					selectBox = new GroupRadioButton();
					((GroupRadioButton)selectBox).GroupName = SelectBoxGroupName;
					if (this.SelectedChangedEventHandler != null) selectBox.AutoPostBack = true;
				}
				selectBox.ID = SelectBoxId;

				SelectBoxContainer.Controls.Add(selectBox);
			}
		}

		/// <summary>
		/// （列表控件）恢复选择项。
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected virtual void DataList_ItemDataBound(object sender, DataListItemEventArgs e)
		{
			if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
			{
				ItemType itemType = GetListItemType(e.Item);

				if (ItemsContains(SelectedItems, itemType))
				{
					CheckBox selectBox = (CheckBox)e.Item.FindControl(SelectBoxId);
					selectBox.Checked = true;
				}
			}
		}
		#endregion




		#region 函数
		/// <summary>
		/// 加载列表。
		/// </summary>
		protected override void LoadList()
		{
			PaginationInfo<DataBindCollection> pageInfo = GetData();

			Pager.RecordCount = pageInfo.RecordCount;

			DataList.DataSource = pageInfo.Records;
			DataList.DataBind();

			Pager.CustomInfoHTML = "<span class=\"PagerCustomInfo\">第 <span class=\"CurrentPage\">" + pageInfo.CurrentPage + "</span>/<span class=\"PageCount\">" + pageInfo.PageCount + "</span> 页";
			Pager.CustomInfoHTML += " 当前显示第 <span class=\"CurrentPageLimit\">" + pageInfo.CurrentPageLimit.Lower + "-" + pageInfo.CurrentPageLimit.Upper + "</span> 条记录</span>";
		}

		/// <summary>
		/// 保存选择项。
		/// </summary>
		protected override bool SaveSelectItems()
		{
			bool change = false;
			foreach (DataListItem item in DataList.Items)
			{
				if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
				{
					CheckBox selectBox = (CheckBox)item.FindControl(SelectBoxId);
					ItemType itemType = GetListItemType(item);
					if (selectBox.Checked)
					{
						change = change | ItemsEnsureItem(SelectedItems, itemType);
					}
					else
					{
						change = change | ItemsRemoveItem(SelectedItems, itemType);
					}
				}
			}

			if (SelectType == SelectBoxType.RadioButton && SelectedItems.Count > 1)
			{
				SelectedItems.RemoveRange(0, SelectedItems.Count - 1);
			}

			return change;
		}

		/// <summary>
		/// 取得 ListItem 的 ItemType。
		/// </summary>
		/// <param name="item">列表的 ListItem。</param>
		/// <returns>ListItem 的 ItemType。</returns>
		protected abstract ItemType GetListItemType(DataListItem item);
		#endregion
	}
}